﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
using System.IO;
using System.Collections;

namespace Delaunay三角剖分
{
    public partial class Form1 : Form
    {
        AcadApplication AcadApp;
        AcadDocument AcadDoc;

        private ArrayList arrayEdges = new ArrayList();
        private ArrayList arrayTris = new ArrayList();

        public Form1()
        {
            InitializeComponent();
        }

        private void 启动CAD()
        {
            try
            {
                AcadApp =
               (AcadApplication)System.Runtime.InteropServices.Marshal.GetActiveObject("AutoCAD.Application");
                AcadDoc = AcadApp.ActiveDocument;
            }
            catch
            {
                OpenFileDialog pOpenDG = new OpenFileDialog();
                pOpenDG.Filter = "CAD文件(*.dwg)|*.dwg|CAD图形文件(*.dxf)|*.dxf";
                pOpenDG.Title = "打开CAD文件";
                pOpenDG.ShowDialog();
                string filePath = pOpenDG.FileName;
                if (filePath == "")
                {
                    MessageBox.Show("选择CAD文件无效！", "文件无效！");
                    Application.Exit();
                }
                AcadApp = new AcadApplication();
                AcadDoc = AcadApp.Documents.Open(filePath, null, null);
            }
            AcadApp.Application.Visible = true;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            启动CAD();
        }

        private void 获取点集坐标数组_Click(object sender, EventArgs e)
        {
            Microsoft.VisualBasic.Interaction.AppActivate(AcadApp.Caption);
            AcadSelectionSet mySelectionSet;
            mySelectionSet = AcadDoc.SelectionSets.Add("NewSelectionSet001");
            Int16[] FilterType = new Int16[1];
            object[] FilterData = new object[1];
            FilterType[0] = 0;
            FilterData[0] = "POINT";
            mySelectionSet.SelectOnScreen(FilterType, FilterData);
            double[] arrPoints = new double[3 * mySelectionSet.Count];
            int count = 0;
            foreach (AcadObject acadObj in mySelectionSet)
            {
                if (acadObj.ObjectName == "AcDbPoint")
                {
                    count++;
                    double[] PointCoord;
                    PointCoord = (Double[])(((AcadPoint)acadObj).Coordinates);
                    arrPoints[3 * count - 3] = PointCoord[0];
                    arrPoints[3 * count - 2] = PointCoord[1];
                    arrPoints[3 * count - 1] = PointCoord[2];
                }
            }
            MessageBox.Show("共选择点的个数为：" + count.ToString());
            AcadDoc.SelectionSets.Item("NewSelectionSet001").Delete();

            //获取点集外围边界 
            int i, startIndex = 0, tempIndex, lastIndex, pointCount = arrPoints.Length / 3;
            for (i = 1; i < pointCount; i++) //寻找X值最小的点号
            {
                if (arrPoints[3 * i] < arrPoints[3 * startIndex])
                {
                    startIndex = i;
                }
            }
            Edge edge = new Edge();
            edge.Start = startIndex;
            lastIndex = startIndex - 1;
            tempIndex = startIndex;
            double[] vector1 = new double[2], vector2 = new double[2];
            vector1[0] = 0; vector1[1] = 100;
            double vector1Length, vector2Length, angleTemp, angleMax, lengthMin;
            angleMax = 0;
            while (lastIndex != startIndex)
            {
                vector1Length = Math.Sqrt(vector1[0] * vector1[0] + vector1[1] * vector1[1]);
                lengthMin = 300;
                for (i = 0; i < pointCount; i++)//找边界
                {
                    if (i != edge.Start)
                    {
                        vector2[0] = arrPoints[3 * i] - arrPoints[3 * tempIndex];
                        vector2[1] = arrPoints[3 * i + 1] - arrPoints[3 * tempIndex + 1];
                        vector2Length = Math.Sqrt(vector2[0] * vector2[0] + vector2[1] * vector2[1]);
                        angleTemp = Math.Acos((vector1[0] * vector2[0] + vector1[1] * vector2[1]) /
                       (vector1Length * vector2Length));
                        if (angleTemp > angleMax)
                        {
                            angleMax = angleTemp;
                            edge.End = i;
                            lengthMin = vector2Length;
                        }
                        else if (angleTemp == angleMax && vector2Length < lengthMin)
                        {
                            edge.End = i;
                            lengthMin = vector2Length;
                        }
                    }
                }
                arrayEdges.Add(edge);
                lastIndex = edge.End;
                edge = new Edge();
                edge.Start = lastIndex;
                angleMax = 0;
                vector1[0] = arrPoints[3 * tempIndex] - arrPoints[3 * lastIndex];
                vector1[1] = arrPoints[3 * tempIndex + 1] - arrPoints[3 * lastIndex + 1];
                tempIndex = lastIndex;
            }

            //绘制边界
            /*Edge[] edges = new Edge[arrayEdges.Count];
            arrayEdges.CopyTo(edges);
            for (i = 0; i < arrayEdges.Count; i++)
            {
                double[] p1 = new double[3], p2 = new double[3];
                p1[0] = arrPoints[3 * edges[i].Start];
                p1[1] = arrPoints[3 * edges[i].Start + 1];
                p1[2] = arrPoints[3 * edges[i].Start + 2];
                p2[0] = arrPoints[3 * edges[i].End];
                p2[1] = arrPoints[3 * edges[i].End + 1];
                p2[2] = arrPoints[3 * edges[i].End + 2];
                AcadDoc.ModelSpace.AddLine(p1, p2);
            }*/

            //生成TIN 
            int newIndex, edgeCount = arrayEdges.Count;
            double angleV1V2Temp, angleV2V3Temp, angleV1V2Max, angleV2V3Max, vector3Length;
            double[] vector3 = new double[2];
            bool isTriExist;
            for (i = 0; i < arrayEdges.Count; i++)
            {
                edge = new Edge();
                edge = (Edge)arrayEdges[i];//取出一条边
                                           //判断三角形是否存在（若本边的左三角已存在，则计算右三角）？
                if (edge.LeftTri == -1)
                {
                    newIndex = -1;//新选取点的索引
                    angleV1V2Max = 0; angleV2V3Max = 0;
                    vector1[0] = arrPoints[3 * edge.End] - arrPoints[3 * edge.Start];
                    vector1[1] = arrPoints[3 * edge.End + 1] - arrPoints[3 * edge.Start + 1];
                    for (int j = 0; j < pointCount; j++)
                    {
                        if (j != edge.Start && j != edge.End)//排除边的端点
                        {
                            vector2[0] = arrPoints[3 * j] - arrPoints[3 * edge.Start];
                            vector2[1] = arrPoints[3 * j + 1] - arrPoints[3 * edge.Start + 1];
                            if (vector1[0] * vector2[1] - vector1[1] * vector2[0] > 0)//如果点j在向量vector1的左侧
 {
                                vector3[0] = arrPoints[3 * j] - arrPoints[3 * edge.End];
                                vector3[1] = arrPoints[3 * j + 1] - arrPoints[3 * edge.End + 1];

                                vector1Length = Math.Sqrt(vector1[0] * vector1[0] + vector1[1] * vector1[1]);

                                vector2Length = Math.Sqrt(vector2[0] * vector2[0] + vector2[1] * vector2[1]);

                                vector3Length = Math.Sqrt(vector3[0] * vector3[0] + vector3[1] * vector3[1]);
                                angleV1V2Temp = Math.Acos((vector1[0] * vector2[0] + vector1[1] *
                               vector2[1])
                                / (vector1Length * vector2Length));
                                angleV2V3Temp = Math.Acos((vector2[0] * vector3[0] + vector2[1] *
                               vector3[1])
                                / (vector2Length * vector3Length));
                                if (angleV2V3Temp > angleV2V3Max)
                                {
                                    angleV2V3Max = angleV2V3Temp;
                                    angleV1V2Max = angleV1V2Temp;
                                    newIndex = j;
                                }
                                else if (angleV2V3Temp == angleV2V3Max && angleV1V2Max >=
                               angleV1V2Temp)
                                {
                                    angleV1V2Max = angleV1V2Temp;
                                    newIndex = j;
                                }
                            }
                        }
                    }
                    if (newIndex != -1)//若找到了这么一个满足要求的点就记录三角形
                    {
                        Tri tri = new Tri();
                        tri.NodeA = edge.Start;
                        tri.NodeB = edge.End;
                        tri.NodeC = newIndex;
                        edge.LeftTri = arrayTris.Count;//设置边的左侧三角形索引
                        isTriExist = false;
                        //记录边1 
                        for (int k = 0; k < arrayEdges.Count; k++)
                        {
                            Edge tempEdge = (Edge)arrayEdges[k];
                            if (tempEdge.Start == edge.Start && tempEdge.End == newIndex)
                            {
                                tempEdge.RightTri = arrayTris.Count;
                                tri.AdjTriB = tempEdge.LeftTri;
                                isTriExist = true;
                                break;
                            }
                            else if (tempEdge.Start == newIndex && tempEdge.End == edge.Start)
                            {
                                tempEdge.LeftTri = arrayTris.Count;
                                tri.AdjTriB = tempEdge.RightTri;
                                isTriExist = true;
                                break;
                            }
                        }
                        if (isTriExist == false)//若不存在这条边就新建一条边
                        {
                            Edge newEdge = new Edge();
                            newEdge.Start = newIndex;
                            newEdge.End = edge.Start;
                            newEdge.LeftTri = arrayTris.Count;
                            arrayEdges.Add(newEdge);
                        }
                        isTriExist = false;
                        //记录边2 
                        for (int k = 0; k < arrayEdges.Count; k++)
                        {
                            Edge tempEdge = (Edge)arrayEdges[k];
                            if (tempEdge.Start == newIndex && tempEdge.End == edge.End)
                            {
                                tempEdge.RightTri = arrayTris.Count;
                                tri.AdjTriA = tempEdge.LeftTri;
                                isTriExist = true;
                                break;
                            }
                            else if (tempEdge.Start == edge.End && tempEdge.End == newIndex)
                            {
                                tempEdge.LeftTri = arrayTris.Count;
                                tri.AdjTriA = tempEdge.RightTri;
                                isTriExist = true;
                                break;
                            }
                        }
                        if (isTriExist == false)//若不存在这条边就新建一条边
                        {
                            Edge newEdge = new Edge();
                            newEdge.Start = edge.End;
                            newEdge.End = newIndex;
                            newEdge.LeftTri = arrayTris.Count;
                            arrayEdges.Add(newEdge);
                        }
                        tri.AdjTriC = edge.RightTri;//如果edge的右三角形不存在，则左三角也不存在
                        arrayTris.Add(tri);
                    }
                }
                else if (edge.RightTri == -1)
                {
                    newIndex = -1;//新选取点的索引
                    angleV1V2Max = 0; angleV2V3Max = 0;
                    vector1[0] = arrPoints[3 * edge.End] - arrPoints[3 * edge.Start];
                    vector1[1] = arrPoints[3 * edge.End + 1] - arrPoints[3 * edge.Start + 1];
                    for (int j = 0; j < pointCount; j++)
                    {
                        if (j != edge.Start && j != edge.End)//排除边的端点
                        {
                            vector2[0] = arrPoints[3 * j] - arrPoints[3 * edge.Start];
                            vector2[1] = arrPoints[3 * j + 1] - arrPoints[3 * edge.Start + 1];
                            if (vector1[0] * vector2[1] - vector1[1] * vector2[0] < 0)
                            {
                                vector3[0] = arrPoints[3 * j] - arrPoints[3 * edge.End];
                                vector3[1] = arrPoints[3 * j + 1] - arrPoints[3 * edge.End + 1];
                                vector1Length = Math.Sqrt(vector1[0] * vector1[0] + vector1[1] *
                               vector1[1]);
                                vector2Length = Math.Sqrt(vector2[0] * vector2[0] + vector2[1] *
                               vector2[1]);
                                vector3Length = Math.Sqrt(vector3[0] * vector3[0] + vector3[1] *
                               vector3[1]);
                                angleV1V2Temp = Math.Acos((vector1[0] * vector2[0] + vector1[1] *
                               vector2[1])
                                / (vector1Length * vector2Length));
                                angleV2V3Temp = Math.Acos((vector2[0] * vector3[0] + vector2[1] *
                               vector3[1])
                                / (vector2Length * vector3Length));
                                if (angleV2V3Temp > angleV2V3Max)
                                {
                                    angleV1V2Max = angleV1V2Temp;
                                    angleV2V3Max = angleV2V3Temp;
                                    newIndex = j;
                                }
                                else if (angleV2V3Temp == angleV2V3Max && angleV1V2Max <=
                               angleV1V2Temp)
                                {
                                    angleV1V2Max = angleV1V2Temp;
                                    newIndex = j;
                                }
                            }
                        }
                    }
                    if (newIndex != -1)//若找到了这么一个满足要求的点就记录三角形
                    {
                        Tri tri = new Tri();
                        tri.NodeA = edge.Start;
                        tri.NodeB = edge.End;
                        tri.NodeC = newIndex;
                        edge.RightTri = arrayTris.Count;//设置边的左侧三角形索引
                        isTriExist = false;
                        //记录边1 
                        for (int k = 0; k < arrayEdges.Count; k++)
                        {
                            Edge tempEdge = (Edge)arrayEdges[k];
                            if (tempEdge.Start == newIndex && tempEdge.End == edge.Start)
                            {
                                tempEdge.RightTri = arrayTris.Count;
                                tri.AdjTriB = tempEdge.LeftTri;
                                isTriExist = true;
                                break;
                            }
                            else if (tempEdge.Start == edge.Start && tempEdge.End == newIndex)
                            {
                                tempEdge.LeftTri = arrayTris.Count;
                                tri.AdjTriB = tempEdge.RightTri;
                                isTriExist = true;
                                break;
                            }
                        }
                        if (isTriExist == false)//若不存在这条边就新建一条边
                        {
                            Edge newEdge = new Edge();
                            newEdge.Start = edge.Start;
                            newEdge.End = newIndex;
                            newEdge.LeftTri = arrayTris.Count;
                            arrayEdges.Add(newEdge);
                        }
                        isTriExist = false;
                        //记录边2 
                        for (int k = 0; k < arrayEdges.Count; k++)
                        {
                            Edge tempEdge = (Edge)arrayEdges[k];
                            if (tempEdge.Start == edge.End && tempEdge.End == newIndex)
                            {
                                tempEdge.RightTri = arrayTris.Count;
                                tri.AdjTriA = tempEdge.LeftTri;
                                isTriExist = true;
                                break;
                            }
                            else if (tempEdge.Start == newIndex && tempEdge.End == edge.End)
                            {
                                tempEdge.LeftTri = arrayTris.Count;
                                tri.AdjTriA = tempEdge.RightTri;
                                isTriExist = true;
                                break;
                            }
                        }
                        if (isTriExist == false)//若不存在这条边就新建一条边
                        {
                            Edge newEdge = new Edge();
                            newEdge.Start = newIndex;
                            newEdge.End = edge.End;
                            newEdge.LeftTri = arrayTris.Count;
                            arrayEdges.Add(newEdge);
                        }
                        tri.AdjTriC = edge.LeftTri;//如果edge的右三角形不存在，则左三角也不存在
                        arrayTris.Add(tri);
                    }
                }
            }

            //绘制三角网
            Tri[] tris = new Tri[arrayTris.Count];
            arrayTris.CopyTo(tris);
            for (i = 0; i < arrayTris.Count; i++)
            {
                double[] p1 = new double[3], p2 = new double[3], p3 = new double[3];
                p1[0] = arrPoints[3 * tris[i].NodeA];
                p1[1] = arrPoints[3 * tris[i].NodeA + 1];
                p1[2] = arrPoints[3 * tris[i].NodeA + 2];
                p2[0] = arrPoints[3 * tris[i].NodeB];
                p2[1] = arrPoints[3 * tris[i].NodeB + 1];
                p2[2] = arrPoints[3 * tris[i].NodeB + 2];
                p3[0] = arrPoints[3 * tris[i].NodeC];
                p3[1] = arrPoints[3 * tris[i].NodeC + 1];
                p3[2] = arrPoints[3 * tris[i].NodeC + 2];
                AcadDoc.ModelSpace.Add3DFace(p1, p2, p3, p1);
            }

            //绘制边
            Edge[] edges = new Edge[arrayEdges.Count];
            arrayEdges.CopyTo(edges);
            for (i = 0; i < arrayEdges.Count; i++)
            {
                double[] p1 = new double[3], p2 = new double[3], textP = new double[3];
                p1[0] = arrPoints[3 * edges[i].Start];
                p1[1] = arrPoints[3 * edges[i].Start + 1];
                p1[2] = arrPoints[3 * edges[i].Start + 2];
                p2[0] = arrPoints[3 * edges[i].End];
                p2[1] = arrPoints[3 * edges[i].End + 1];
                p2[2] = arrPoints[3 * edges[i].End + 2];
                textP[0] = (p1[0] + p2[0]) / 2;
                textP[1] = (p1[1] + p2[1]) / 2;
                System.Threading.Thread.Sleep(100);
                AcadDoc.ModelSpace.AddLine(p1, p2);
                AcadDoc.ModelSpace.AddText(i.ToString(), textP, 2.5);
                AcadDoc.Application.Update();
            }
        }
    }
}
